Import cal3d

Class CalSubmesh

	Field m_coreSubmesh:CalCoreSubmesh
	Field m_vectorMorphTargetWeight:Float[]
	Field m_vectorVertex:CalVector[]
	Field m_vectorNormal:CalVector[]
	Field m_vectorvectorTangentSpace:CalTangentSpace[][]
	Field m_vectorFace:CalFace[]
	Field m_vectorPhysicalProperty:CalPhysicalProperty[]
	Field m_vertexCount:Int
	Field m_faceCount:Int
	Field m_coreMaterialId:Int
	Field m_bInternalData:Bool
	
	Method New()
		 m_coreSubmesh = null
		 m_vectorMorphTargetWeight = New Float[0]
		 m_vectorVertex = New CalVector[0]
		 m_vectorNormal = New CalVector[0]
		 m_vectorvectorTangentSpace = New CalTangentSpace[0][]
		 m_vectorFace = New CalFace[0]
		 m_vectorPhysicalProperty = New CalPhysicalProperty[0]
		 m_vertexCount = 0
		 m_faceCount = 0
		 m_coreMaterialId = -1
		 m_bInternalData = False	
	End
	
	Method New(coreSubmesh:CalCoreSubmesh)
	
		 m_coreSubmesh = coreSubmesh
		 m_vectorMorphTargetWeight = New Float[coreSubmesh.getCoreSubMorphTargetCount()]
		 m_vectorVertex = New CalVector[0]
		 m_vectorNormal = New CalVector[0]
		 m_vectorvectorTangentSpace = New CalTangentSpace[0][]
		 m_vectorFace = New CalFace[coreSubmesh.getFaceCount()]
		 m_vectorPhysicalProperty = New CalPhysicalProperty[0]
		 m_vertexCount = 0
		 m_faceCount = 0
		 m_coreMaterialId = -1
		 m_bInternalData = False

		For Local faceId:Int = 0 To m_vectorFace.Length-1
			m_vectorFace[faceId] = New CalFace()
		Next

		setLodLevel(1)
		
		Local morphTargetCount:Int = coreSubmesh.getCoreSubMorphTargetCount()
		For Local morphTargetId:Int = 0 To morphTargetCount-1
			m_vectorMorphTargetWeight[morphTargetId] = 0
		Next

		If coreSubmesh.getSpringCount() > 0 Then
			Local vertexCount:Int = coreSubmesh.getVertexCount()
	
			m_vectorVertex = New CalVector[vertexCount]
			m_vectorNormal = New CalVector[vertexCount]
	
			m_vectorvectorTangentSpace = New CalTangentSpace[coreSubmesh.getVectorVectorTangentSpace().Length][]
	
			m_vectorPhysicalProperty = New CalPhysicalProperty[vertexCount]
	
			' get the vertex vector of the core submesh
			Local vectorVertex:CalVertex[] = coreSubmesh.getVectorVertex()
	
			' copy the data from the core submesh as default values
			For Local vertexId:Int = 0 To vertexCount-1
				' copy the vertex data
				m_vectorVertex[vertexId] = new CalVector(vectorVertex[vertexId].position)
				Local physicalProperty:CalPhysicalProperty = New CalPhysicalProperty()
				physicalProperty.position.assign(vectorVertex[vertexId].position)
				physicalProperty.positionOld.assign(vectorVertex[vertexId].position)
				m_vectorPhysicalProperty[vertexId] = physicalProperty
	
				' copy the normal data
				m_vectorNormal[vertexId] = New CalVector(vectorVertex[vertexId].normal)
			Next
	
			m_bInternalData = True
		Endif


	End	
	
	
	Method getCoreSubmesh:CalCoreSubmesh()
		Return m_coreSubmesh
	End
	
	Method getCoreMaterialId:Int()
		Return m_coreMaterialId
	End
	
	Method getFaceCount:Int()
		Return m_faceCount
	End
	
	Method getFaces:Int(faceBuffer:Int[])
		Local j:Int = 0
		For Local i:Int = 0 To m_faceCount-1
			Local faceVertId:Int[] = m_vectorFace[i].vertexId
			faceBuffer[j    ] = faceVertId[0]
			faceBuffer[j + 1] = faceVertId[1]
			faceBuffer[j + 2] = faceVertId[2]
			j = j + 3
		Next
	
		return m_faceCount		
	End
	
	Method getVectorNormal:CalVector[]()
		Return m_vectorNormal
	End 
	
	Method getVectorVectorTangentSpace:CalTangentSpace[][]()
		Return m_vectorvectorTangentSpace
	End
	
	Method getVectorPhysicalProperty:CalPhysicalProperty[]()
		Return m_vectorPhysicalProperty
	End
	
	Method getVectorVertex:CalVector[]()
		Return m_vectorVertex
	End
	
	Method getVertexCount:Int()
		Return m_vertexCount
	End
	
	Method hasInternalData:Bool()
		Return m_bInternalData
	End
	
	Method disableInternalData:Void()
		If m_bInternalData = True then
			m_vectorVertex = New CalVertex[0]
			m_vectorNormal = New CalVector[0]
			m_vectorvectorTangentSpace = New CalTangentSpace[0]
			m_vectorPhysicalProperty = New CalPhysicalProperty[0]
			m_bInternalData = False
		endif		
	End
	
	Method setCoreMaterialId:Void(coreMaterialId:Int)
		m_coreMaterialId = coreMaterialId
	End
	
	Method setLodLevel:Void(lodLevel:Float)
		' clamp the lod level to [0.0, 1.0]
		If lodLevel < 0 Then 
			lodLevel = 0
		Elseif lodLevel > 1 Then
			lodLevel = 1
		Endif	
		' get the lod count of the core submesh
		Local lodCount = m_coreSubmesh.getLodCount()
	
		' calculate the target lod count
		lodCount = Floor((1 - lodLevel) * lodCount)
	
		' calculate the new number of vertices
		m_vertexCount = m_coreSubmesh.getVertexCount() - lodCount
	
		' get face vector of the core submesh
		Local vectorFace:CalFace[] = m_coreSubmesh.getVectorFace()
	
		' get face vector of the core submesh
		Local vectorVertex:CalVertex[] = m_coreSubmesh.getVectorVertex()
	
		' calculate the new number of faces
		m_faceCount = vectorFace.Length
	
		For Local vertexId:Int = vectorVertex.Length-1 To m_vertexCount Step -1
			m_faceCount -= vectorVertex[vertexId].faceCollapseCount
		Next
	
		' fill the face vector with the collapsed vertex ids
		For Local faceId:Int = 0 To m_faceCount-1
			For Local vertexId:Int = 0 To 2
				' get the vertex id
				Local collapsedVertexId:Int = vectorFace[faceId].vertexId[vertexId]
	
				' collapse the vertex id until it fits into the current lod level
				' FIXME: this may cause an infinit loop
				While collapsedVertexId >= m_vertexCount
					collapsedVertexId = vectorVertex[collapsedVertexId].collapseId
				Wend
	
				' store the collapse vertex id in the submesh face vector
				m_vectorFace[faceId].vertexId[vertexId] = collapsedVertexId
			Next
		Next	
	End
	
	Method isTangentsEnabled:Bool(mapId:Int)
		Return m_coreSubmesh.isTangentsEnabled(mapId)
	End
	
	Method enableTangents:Bool(mapId:Int, enabled:Bool)
		If m_coreSubmesh.enableTangents(mapId, enabled) = False Then
			Return False
		Endif
		If m_bInternalData = False Then
			Return True
		Endif
		If enabled = False then
			m_vectorvectorTangentSpace[mapId] = New CalTangentSpace[0]
			Return True
		Endif
	
		m_vectorvectorTangentSpace[mapId] = New CalTangentSpace[m_coreSubmesh.getVertexCount()]
	
		' get the tangent space vector of the core submesh
		Local vectorTangentSpace = m_coreSubmesh.getVectorVectorTangentSpace()[mapId]
	
		' copy the data from the core submesh as default values
		Local vertexCount = m_coreSubmesh.getVertexCount()
		For Local vertexId:Int = 0 To vertexCount-1
			' copy the tangent space data
			Local tangentSpace:CalTangentSpace = New CalTangentSpace()
			tangentSpace.tangent.assign(vectorTangentSpace[vertexId].tangent)
			tangentSpace.crossFactor = vectorTangentSpace[vertexId].crossFactor
			m_vectorvectorTangentSpace[mapId][vertexId] = tangentSpace
		Next
	
		return true		
	End
	
	Method getVectorWeight:Float()
		Print "Not Implemented yet"
		Return 0
	End


	Method setMorphTargetWeight:Void(blendId:Int, weight:Float)
		m_vectorMorphTargetWeight[blendId] = weight
	End
	
	Method getMorphTargetWeight:Float(blendId:Int)
		Return m_vectorMorphTargetWeight[blendId]
	End	
	
	Method getBaseWeight:Float()
		Local baseWeight:Float = 1
		Local morphTargetCount:Int = getMorphTargetWeightCount()
		For Local morphTargetId:Int = 0 To morphTargetCount-1
			baseWeight -= m_vectorMorphTargetWeight[morphTargetId]
		Next
	
		return baseWeight		
	End
	
	Method getMorphTargetWeightCount:Int()
		Return m_vectorMorphTargetWeight.Length
	End
	
	Method getVectorMorphTargetWeight:Float[]()
		Return m_vectorMorphTargetWeight
	End

End Class